home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / oleo130s.zip / OLEO130S.TAR / oleo-1.3 / busi.c < prev    next >
C/C++ Source or Header  |  1993-03-14  |  10KB  |  563 lines

  1. /*    Copyright (C) 1990, 1992, 1993 Free Software Foundation, Inc.
  2.  
  3. This file is part of Oleo, the GNU Spreadsheet.
  4.  
  5. Oleo is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9.  
  10. Oleo is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with Oleo; see the file COPYING.  If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include "funcdef.h"
  20. #include "sysdef.h"
  21.  
  22. #include "global.h"
  23. #include "cell.h"
  24. #include "eval.h"
  25. #include "errors.h"
  26.  
  27. struct value
  28.   {
  29.     int type;
  30.     union vals x;
  31.   };
  32.  
  33. #define Float    x.c_d
  34. #define String    x.c_s
  35. #define Int    x.c_l
  36. #define Value    x.c_i
  37. #define Rng    x.c_r
  38.  
  39. static double
  40. pmt (principal, rate, term)
  41.      double principal;
  42.      double rate;
  43.      double term;
  44. {
  45.   return (principal * rate) / (1 - pow (1 + rate, -(term)));
  46. }
  47.  
  48.  
  49. static int
  50. npv (rng, rate, putres)
  51.      struct rng *rng;
  52.      double rate;
  53.      double *putres;
  54. {
  55.   double npv;
  56.   int i;
  57.   double f;
  58.   CELL *cell_ptr;
  59.   char *strptr;
  60.  
  61.   find_cells_in_range (rng);
  62.   for (i = 1, npv = 0.0; cell_ptr = next_cell_in_range (); i++)
  63.     {
  64.       switch (GET_TYP (cell_ptr))
  65.     {
  66.     case 0:
  67.       f = 0.0;
  68.       goto know_f;
  69.  
  70.     case TYP_INT:
  71.       f = (double) (cell_ptr->cell_int);
  72.       goto know_f;
  73.  
  74.     case TYP_FLT:
  75.       f = cell_ptr->cell_flt;
  76.       goto know_f;
  77.  
  78.     case TYP_STR:
  79.       strptr = cell_ptr->cell_str;
  80.       f = astof (&strptr);
  81.       if (*strptr)
  82.         return NON_NUMBER;
  83.     know_f:
  84.       npv += f * (1.0 / (pow (1.0 + rate, (double) i)));
  85.       break;
  86.  
  87.     case TYP_ERR:
  88.       return cell_ptr->cell_err;
  89.  
  90.     default:
  91.       return NON_NUMBER;
  92.     }
  93.     }
  94.  
  95.   *putres = npv;
  96.   return 0;
  97. }
  98.  
  99. static void
  100. do_pmt (p)
  101.      struct value *p;
  102. {
  103.   p->Float = pmt (p->Float, (p + 1)->Float, (p + 2)->Float);
  104. }
  105.  
  106. static void
  107. do_pv (p)
  108.      struct value *p;
  109. {
  110.   double payment, interest, term;
  111.  
  112.   payment = p[0].Float;
  113.   interest = p[1].Float;
  114.   term = p[2].Float;
  115.  
  116.   p->Float = payment * ((1 - pow (1 + interest, -term)) / interest);
  117. }
  118.  
  119. static void
  120. do_npv (p)
  121.      struct value *p;
  122. {
  123.   int tmp;
  124.  
  125.   tmp = npv (&(p->Rng), (p + 1)->Float, &(p->Float));
  126.   if (tmp)
  127.     {
  128.       p->Value = tmp;
  129.       p->type = TYP_ERR;
  130.     }
  131.   p->type = TYP_FLT;
  132. }
  133.  
  134. static void
  135. do_irr (p)
  136.      struct value *p;
  137. {
  138.   double try;
  139.   double res;
  140.   double mint, maxt;
  141.   double minr, maxr;
  142.   int i;
  143.   int tmp;
  144.  
  145.   minr = maxr = 0;
  146.   mint = maxt = 0;
  147.   while (minr >= 0)
  148.     {
  149.       mint += 1;
  150.       tmp = npv (&(p->Rng), mint, &minr);
  151.       if (tmp)
  152.     {
  153.       p->Value = tmp;
  154.       p->type = TYP_ERR;
  155.       return;
  156.     }
  157.     }
  158.   while (maxr <= 0)
  159.     {
  160.       maxt -= 1;
  161.       tmp = npv (&(p->Rng), maxt, &maxr);
  162.       if (tmp)
  163.     {
  164.       p->Value = tmp;
  165.       p->type = TYP_ERR;
  166.       return;
  167.     }
  168.     }
  169.   try = (p + 1)->Float;
  170.   for (i = 0;; i++)
  171.     {
  172.       if (i == 40)
  173.     {
  174.       p->Value = BAD_INPUT;
  175.       p->type = TYP_ERR;
  176.       return;
  177.     }
  178.       tmp = npv (&(p->Rng), try, &res);
  179.       if (tmp)
  180.     {
  181.       p->Value = tmp;
  182.       p->type = TYP_ERR;
  183.       return;
  184.     }
  185.       if (fabs (res * 1000000.0) < 1)
  186.     break;
  187.       if (res > 0)
  188.     {
  189.       maxt = try;
  190.       maxr = res;
  191.     }
  192.       else if (res < 0)
  193.     {
  194.       mint = try;
  195.       minr = res;
  196.     }
  197.       if (minr / -10 > maxr)
  198.     {
  199.       /* it is quite near maxt */
  200.       try = (maxt * 10 + mint) / 11;
  201.     }
  202.       else if (minr / -2 > maxr)
  203.     {
  204.       try = (maxt * 2 + mint) / 3;
  205.     }
  206.       else if (minr * -10 < maxr)
  207.     {
  208.       /* It is quite near mint */
  209.       try = (maxt + mint * 10) / 11;
  210.     }
  211.       else if (minr * -2 < maxr)
  212.     {
  213.       try = (maxt + mint * 2) / 3;
  214.     }
  215.       else
  216.     try = (maxt + mint) / 2;
  217.     }
  218.   p->Float = try;
  219.   p->type = TYP_FLT;
  220. }
  221.  
  222. static void
  223. do_fv (p)
  224.      struct value *p;
  225. {
  226.   double payment = p->Float;
  227.   double interest = (p + 1)->Float;
  228.   double term = (p + 2)->Float;
  229.  
  230.   p->Float = payment * ((pow (1 + interest, term) - 1) / interest);
  231. }
  232.  
  233. static void
  234. do_rate (p)
  235.      struct value *p;
  236. {
  237.   double future = p->Float;
  238.   double present = (p + 1)->Float;
  239.   double term = (p + 2)->Float;
  240.  
  241.   p->Float = pow (future / present, 1 / term) - 1;
  242. }
  243.  
  244. static void
  245. do_term (p)
  246.      struct value *p;
  247. {
  248.   double payment = p->Float;
  249.   double interest = (p + 1)->Float;
  250.   double future = (p + 2)->Float;
  251.  
  252.   p->Float = log (1 + future * (interest / payment)) / log (1 + interest);
  253. }
  254.  
  255. static void
  256. do_cterm (p)
  257.      struct value *p;
  258. {
  259.   double interest = (p)->Float;
  260.   double future = (p + 1)->Float;
  261.   double present = (p + 2)->Float;
  262.  
  263.   p->Float = log (future / present) / log (1 + interest);
  264. }
  265.  
  266. static void
  267. do_sln (p)
  268.      struct value *p;
  269. {
  270.   double cost = (p)->Float;
  271.   double salvage = (p + 1)->Float;
  272.   double life = (p + 2)->Float;
  273.  
  274.   p->Float = (cost - salvage) / life;
  275. }
  276.  
  277. static void
  278. do_syd (p)
  279.      struct value *p;
  280. {
  281.   double cost, salvage, life, period;
  282.  
  283.   cost = p->Float;
  284.   salvage = (p + 1)->Float;
  285.   life = (p + 2)->Float;
  286.   period = (p + 3)->Float;
  287.  
  288.   if (period > life)        /* JF is this right? */
  289.     p->Float = salvage;
  290.   else
  291.     p->Float = ((cost - salvage) * (life - period + 1)) / (life * ((life + 1) / 2));
  292. }
  293.  
  294.  
  295. static void
  296. do_ddb (p)
  297.      struct value *p;
  298. {
  299.   double cost = (p)->Float;
  300.   double salvage = (p + 1)->Float;
  301.   long life = (p + 2)->Int;
  302.   long period = (p + 3)->Int;
  303.  
  304.   double bookval, tmp;
  305.   long n;
  306.  
  307.   if (period < 1 || period > life || life < 1)
  308.     {
  309.       p->Value = OUT_OF_RANGE;
  310.       p->type = TYP_ERR;
  311.       return;
  312.     }
  313.   bookval = cost;
  314.   tmp = 0;
  315.   for (n = 0; n < period; n++)
  316.     {
  317.       tmp = (bookval * 2) / life;
  318.       bookval -= tmp;
  319.       if (bookval < salvage)
  320.     {
  321.       tmp += bookval - salvage;
  322.       bookval = salvage;
  323.     }
  324.     }
  325.   p->Float = tmp;
  326. }
  327.  
  328. static void
  329. do_anrate (p)
  330.      struct value *p;
  331. {
  332.   double in_pmt = (p)->Float;
  333.   double present = (p + 1)->Float;
  334.   double term = (p + 2)->Float;
  335.  
  336.   double tr_lo, tr_hi;
  337.   double mytry;
  338.   double try_pmt;
  339.   int n;
  340.  
  341.   if (in_pmt * term == present)
  342.     {
  343.       p->Float = 0.0;
  344.       return;
  345.     }
  346.   if (in_pmt * term < present)
  347.     {
  348.       tr_lo = -1;
  349.       tr_hi = 0;
  350.       while (pmt (present, tr_lo, term) > in_pmt)
  351.     {
  352.       tr_hi = tr_lo;
  353.       tr_lo *= 2;
  354.     }
  355.     }
  356.   else
  357.     {
  358.       tr_lo = 0;
  359.       tr_hi = 1;
  360.       while (pmt (present, tr_hi, term) < in_pmt)
  361.     {
  362.       tr_lo = tr_hi;
  363.       tr_hi *= 2;
  364.     }
  365.     }
  366.   for (n = 0; n < 40; n++)
  367.     {
  368.       mytry = (tr_lo + tr_hi) / 2;
  369.       try_pmt = pmt (present, mytry, term);
  370.       if (try_pmt < in_pmt)
  371.     tr_lo = mytry;
  372.       else if (try_pmt > in_pmt)
  373.     tr_hi = mytry;
  374.       else
  375.     break;
  376.     }
  377.   p->Float = mytry;
  378. }
  379.  
  380. static void
  381. do_anterm (p)
  382.      struct value *p;
  383. {
  384.   double payment = (p)->Float;
  385.   double principal = (p + 1)->Float;
  386.   double rate = (p + 2)->Float;
  387.  
  388.   p->Float = (-log (1 - principal * (rate / payment))) / log (1 + rate);
  389. }
  390.  
  391.  
  392. static void
  393. do_balance (p)
  394.      struct value *p;
  395. {
  396.   double principal = (p)->Float;
  397.   double rate = (p + 1)->Float;
  398.   long term = (p + 2)->Int;
  399.   long period = (p + 3)->Int;
  400.  
  401.   double tmp_pmt, int_part;
  402.   long num;
  403.  
  404.   if (term < period)
  405.     {
  406.       p->Value = OUT_OF_RANGE;
  407.       p->type = TYP_ERR;
  408.       return;
  409.     }
  410.   tmp_pmt = pmt (principal, rate, (double) term);
  411.   for (num = 0; num < period; num++)
  412.     {
  413.       int_part = rate * principal;
  414.       if (int_part > tmp_pmt)
  415.     {
  416.       p->Value = OUT_OF_RANGE;
  417.       p->type = TYP_ERR;
  418.       return;
  419.     }
  420.       principal -= tmp_pmt - int_part;
  421.     }
  422.   p->Float = principal;
  423. }
  424.  
  425. static void
  426. do_paidint (p)
  427.      struct value *p;
  428. {
  429.   double principal = (p)->Float;
  430.   double rate = (p + 1)->Float;
  431.   long term = (p + 2)->Int;
  432.   long period = (p + 3)->Int;
  433.  
  434.   double tmp_pmt, int_part, retval;
  435.   long num;
  436.  
  437.   if (term < period)
  438.     {
  439.       p->Value = OUT_OF_RANGE;
  440.       p->type = TYP_ERR;
  441.       return;
  442.     }
  443.   tmp_pmt = pmt (principal, rate, (double) term);
  444.   retval = 0;
  445.   for (num = 0; num < period; num++)
  446.     {
  447.       int_part = rate * principal;
  448.       if (int_part > tmp_pmt)
  449.     {
  450.       p->Value = OUT_OF_RANGE;
  451.       p->type = TYP_ERR;
  452.       return;
  453.     }
  454.       principal -= tmp_pmt - int_part;
  455.       retval += int_part;
  456.     }
  457.   p->Float = retval;
  458. }
  459.  
  460. static void
  461. do_kint (p)
  462.      struct value *p;
  463. {
  464.   double principal = (p)->Float;
  465.   double rate = (p + 1)->Float;
  466.   long term = (p + 2)->Int;
  467.   long period = (p + 3)->Int;
  468.  
  469.   double tmp_pmt, int_part = 0;
  470.   long num;
  471.  
  472.   if (term < period)
  473.     {
  474.       p->Value = OUT_OF_RANGE;
  475.       p->type = TYP_ERR;
  476.       return;
  477.     }
  478.  
  479.   tmp_pmt = pmt (principal, rate, (double) term);
  480.   for (num = 0; num < period; num++)
  481.     {
  482.       int_part = rate * principal;
  483.       if (int_part > tmp_pmt)
  484.     {
  485.       p->Value = OUT_OF_RANGE;
  486.       p->type = TYP_ERR;
  487.       return;
  488.     }
  489.       principal -= tmp_pmt - int_part;
  490.     }
  491.   p->Float = int_part;
  492. }
  493.  
  494. static void
  495. do_kprin (p)
  496.      struct value *p;
  497. {
  498.   double principal = (p)->Float;
  499.   double rate = (p + 1)->Float;
  500.   long term = (p + 2)->Int;
  501.   long period = (p + 3)->Int;
  502.   double tmp_pmt, int_part = 0;
  503.   long num;
  504.  
  505.   if (term < period)
  506.     {
  507.       p->Value = OUT_OF_RANGE;
  508.       p->type = TYP_ERR;
  509.       return;
  510.     }
  511.  
  512.   tmp_pmt = pmt (principal, rate, (double) term);
  513.   for (num = 0; num < period; num++)
  514.     {
  515.       int_part = rate * principal;
  516.       if (int_part > tmp_pmt)
  517.     {
  518.       p->Value = OUT_OF_RANGE;
  519.       p->type = TYP_ERR;
  520.       return;
  521.     }
  522.       principal -= tmp_pmt - int_part;
  523.     }
  524.   p->Float = tmp_pmt - int_part;
  525. }
  526.  
  527. static void
  528. do_compbal (p)
  529.      struct value *p;
  530. {
  531.   double principal = (p)->Float;
  532.   double rate = (p + 1)->Float;
  533.   double term = (p + 2)->Float;
  534.  
  535.   p->Float = principal * pow (1 + rate, term);
  536. }
  537.  
  538. struct function busi_funs[] =
  539. {
  540.   {C_FN2, X_A2, "RF", do_npv, "npv"},
  541.   {C_FN2, X_A2, "RF", do_irr, "irr"},
  542.  
  543.   {C_FN3, X_A3, "FFF", do_pmt, "pmt"},
  544.   {C_FN3, X_A3, "FFF", do_pv, "pv"},
  545.   {C_FN3, X_A3, "FFF", do_fv, "fv"},
  546.   {C_FN3, X_A3, "FFF", do_rate, "rate"},
  547.   {C_FN3, X_A3, "FFF", do_term, "term"},
  548.   {C_FN3, X_A3, "FFF", do_cterm, "cterm"},
  549.   {C_FN3, X_A3, "FFF", do_sln, "sln"},
  550.   {C_FN3, X_A3, "FFF", do_anrate, "anrate"},
  551.   {C_FN3, X_A3, "FFF", do_anterm, "anterm"},
  552.   {C_FN3, X_A3, "FFF", do_compbal, "compbal"},
  553.  
  554.   {C_FN4, X_A4, "FFFF", do_syd, "syd"},
  555.   {C_FN4, X_A4, "FFII", do_ddb, "ddb"},
  556.   {C_FN4, X_A4, "FFII", do_balance, "balance"},
  557.   {C_FN4, X_A4, "FFII", do_paidint, "paidint"},
  558.   {C_FN4, X_A4, "FFII", do_kint, "kint"},
  559.   {C_FN4, X_A4, "FFII", do_kprin, "kprin"},
  560.  
  561.   {0, 0, "", 0, 0},
  562. };
  563.